/*
命令行参数解析工具，用于解析程序启动时传入的命令行 flag（参数），并提供便捷的接口获取不同类型的参数值
包初始化时自动解析命令行参数（os.Args[1:]），解析结果存入flagSet的values map 中，后续通过导出的String/Int等方法即可快速获取转换后的参数值，简化了命令行参数的处理逻辑
*/
package flag

import (
	"fmt"
	"gameServer/errors"      // 自定义错误处理包，用于返回解析过程中的错误
	"gameServer/utils/rconv" // 类型转换工具包，用于将字符串参数转为目标类型
	"log"                    // 日志工具，用于输出解析过程中的错误信息
	"os"                     // 提供操作系统相关功能，此处用于获取命令行参数
	"time"                   // 时间处理包，用于支持Duration类型的参数解析
)

// commandLine 全局的flag集合实例，初始化时传入程序的命令行参数（排除程序名本身）
// os.Args[0]是程序名，os.Args[1:]是实际的命令行参数
var commandLine = newFlagSet(os.Args[1:])

// init 包初始化函数，在包加载时自动调用，用于解析命令行参数
// 确保程序启动时就完成所有flag的解析，后续可直接通过导出函数获取参数值
func init() {
	commandLine.parse()
}

// Has 检查指定key的flag是否存在于命令行参数中
// 参数：key - 要检查的flag名称（如"port"）
// 返回值：bool - 存在返回true，否则返回false
func Has(key string) bool {
	return commandLine.has(key)
}

// String 获取字符串类型的flag值
// 参数：
//
//	key - flag名称
//	def - 可选的默认值（当flag不存在时使用）
//
// 返回值：string - flag的值（存在则返回解析后的值，否则返回默认值，无默认值则返回空字符串）
func String(key string, def ...string) string {
	return commandLine.string(key, def...)
}

// Bool 获取布尔类型的flag值
// 参数：
//
//	key - flag名称
//	def - 可选的默认值（当flag不存在时使用）
//
// 返回值：bool - flag的值（存在则返回解析后的值，否则返回默认值，无默认值则返回false）
func Bool(key string, def ...bool) bool {
	return commandLine.bool(key, def...)
}

// Int 获取int类型的flag值
// 参数：
//
//	key - flag名称
//	def - 可选的默认值（当flag不存在时使用）
//
// 返回值：int - flag的值（存在则返回解析后的值，否则返回默认值，无默认值则返回0）
func Int(key string, def ...int) int {
	return commandLine.int(key, def...)
}

// Int8 获取int8类型的flag值（逻辑同Int，仅类型不同）
func (f *flagSet) Int8(key string, def ...int8) int8 {
	if val, ok := f.values[key]; ok {
		return rconv.Int8(val)
	}

	if len(def) > 0 {
		return def[0]
	}

	return 0
}

// Int16 获取int16类型的flag值（逻辑同Int，仅类型不同）
func Int16(key string, def ...int16) int16 {
	return commandLine.int16(key, def...)
}

// Int32 获取int32类型的flag值（逻辑同Int，仅类型不同）
func Int32(key string, def ...int32) int32 {
	return commandLine.int32(key, def...)
}

// Int64 获取int64类型的flag值（逻辑同Int，仅类型不同）
func Int64(key string, def ...int64) int64 {
	return commandLine.int64(key, def...)
}

// Uint 获取uint类型的flag值（逻辑同Int，仅类型为无符号整数）
func Uint(key string, def ...uint) uint {
	return commandLine.uint(key, def...)
}

// Uint8 获取uint8类型的flag值（逻辑同Uint，仅类型不同）
func Uint8(key string, def ...uint8) uint8 {
	return commandLine.uint8(key, def...)
}

// Uint16 获取uint16类型的flag值（逻辑同Uint，仅类型不同）
func Uint16(key string, def ...uint16) uint16 {
	return commandLine.uint16(key, def...)
}

// Uint32 获取uint32类型的flag值（逻辑同Uint，仅类型不同）
func Uint32(key string, def ...uint32) uint32 {
	return commandLine.uint32(key, def...)
}

// Uint64 获取uint64类型的flag值（逻辑同Uint，仅类型不同）
func Uint64(key string, def ...uint64) uint64 {
	return commandLine.uint64(key, def...)
}

// Float32 获取float32类型的flag值（逻辑同Int，仅类型为单精度浮点数）
func Float32(key string, def ...float32) float32 {
	return commandLine.float32(key, def...)
}

// Float64 获取float64类型的flag值（逻辑同Int，仅类型为双精度浮点数）
func Float64(key string, def ...float64) float64 {
	return commandLine.float64(key, def...)
}

// Duration 获取time.Duration类型的flag值（支持如"10s"、"5m"等时间字符串解析）
// 参数：
//
//	key - flag名称
//	def - 可选的默认值（当flag不存在时使用）
//
// 返回值：time.Duration - flag的值（存在则返回解析后的值，否则返回默认值，无默认值则返回0）
func Duration(key string, def ...time.Duration) time.Duration {
	return commandLine.duration(key, def...)
}

// flagSet 命令行参数解析器核心结构体，负责存储原始参数和解析后的键值对
type flagSet struct {
	args   []string          // 原始命令行参数切片（os.Args[1:]）
	values map[string]string // 解析后的flag键值对（key为flag名称，value为原始字符串值）
}

// newFlagSet 创建一个新的flagSet实例
// 参数：args - 命令行参数切片（通常为os.Args[1:]）
// 返回值：*flagSet - 初始化后的参数解析器
func newFlagSet(args []string) *flagSet {
	f := &flagSet{
		args:   args,
		values: make(map[string]string), // 初始化存储键值对的map
	}
	f.parse() // 立即解析参数

	return f
}

// parse 循环解析所有命令行参数，直到所有参数解析完成
func (f *flagSet) parse() {
	for {
		// 解析单个参数，返回是否解析到有效flag以及可能的错误
		seen, err := f.parseOne()
		if seen {
			// 若解析到有效flag，继续解析下一个
			continue
		}

		if err == nil {
			// 无错误且未解析到flag，说明所有参数解析完成，退出循环
			break
		}

		// 解析出错，输出错误日志（不终止程序，继续解析后续参数）
		log.Println(err)
	}
}

// parseOne 解析单个命令行参数，提取flag名称和值
// 返回值：
//
//	bool - 是否解析到有效flag
//	error - 解析过程中发生的错误（如格式错误）
func (f *flagSet) parseOne() (bool, error) {
	// 若没有剩余参数，返回未解析到flag
	if len(f.args) == 0 {
		return false, nil
	}

	s := f.args[0]
	// 检查参数是否为flag（以"-"开头，且长度至少为2，如"-key"或"--key"）
	if len(s) < 2 || s[0] != '-' {
		return false, nil // 不是flag，返回未解析到
	}

	// 判断是"-"开头（短flag）还是"--"开头（长flag）
	numMinuses := 1
	if s[1] == '-' {
		numMinuses++
		// 若参数是"--"，表示后续不再有flag，仅作为分隔符，移除该参数并停止解析
		if len(s) == 2 {
			f.args = f.args[1:]
			return false, nil
		}
	}

	// 提取flag名称（去掉开头的"-"或"--"）
	name := s[numMinuses:]
	// 检查flag名称格式是否合法（不能为空，且不能以"-"或"="开头）
	if len(name) == 0 || name[0] == '-' || name[0] == '=' {
		return false, errors.New(fmt.Sprintf("bad flag syntax: %s", s))
	}

	// 移除当前解析的参数（已提取flag名称）
	f.args = f.args[1:]

	hasValue := false // 标记flag是否带有值
	value := ""       // 存储flag的值

	// 检查flag名称中是否包含"="（如"--key=value"或"-key=value"）
	for i := 1; i < len(name); i++ { // 从索引1开始，避免"="作为第一个字符（已在前面检查）
		if name[i] == '=' {
			// 提取"="后面的值，截断名称为"="前面的部分
			value = name[i+1:]
			hasValue = true
			name = name[0:i]
			break
		}
	}

	// 若flag没有通过"="带值，检查下一个参数是否为值（非flag的参数，即不以"-"开头）
	if !hasValue && len(f.args) > 0 {
		if s = f.args[0]; s[0] != '-' {
			// 下一个参数是值，提取该值并移除该参数
			hasValue = true
			value, f.args = f.args[0], f.args[1:]
		}
	}

	// 将解析到的flag名称和值存入map
	f.values[name] = value

	return true, nil // 成功解析到一个flag
}

// has 检查指定key的flag是否存在（内部实现，供导出函数Has调用）
func (f *flagSet) has(key string) bool {
	_, ok := f.values[key]
	return ok
}

// string 获取字符串类型的flag值（内部实现，供导出函数String调用）
func (f *flagSet) string(key string, def ...string) string {
	if val, ok := f.values[key]; ok {
		return val // 存在则返回原始字符串值
	}

	// 不存在则返回默认值（若有），否则返回空字符串
	if len(def) > 0 {
		return def[0]
	}

	return ""
}

// bool 获取布尔类型的flag值（内部实现，供导出函数Bool调用）
func (f *flagSet) bool(key string, def ...bool) bool {
	if val, ok := f.values[key]; ok {
		// 布尔类型特殊处理：若flag存在但值为空（如"-debug"），默认视为true
		if val == "" {
			return true
		}
		// 否则通过xconv.Bool转换为bool类型（支持"true"/"false"/"1"/"0"等）
		return rconv.Bool(val)
	}

	// 不存在则返回默认值（若有），否则返回false
	if len(def) > 0 {
		return def[0]
	}

	return false
}

//
//// int 获取int类型的flag值（内部实现，供导出函数Int调用）
//func (f *flagSet) int(key string, def ...int) int {
//	if val, ok := f.values[key]; ok {
//		// 通过xconv.Int将字符串值转为int类型（自动处理数字字符串）
//		return rconv.Int(val)
//	}
//
//	// 不存在则返回默认值（若有），否则返回0
//	if len(def) > 0 {
//		return def[0]
//	}
//
//	return 0
//}

// duration 获取time.Duration类型的flag值（内部实现，供导出函数Duration调用）
func (f *flagSet) duration(key string, def ...time.Duration) time.Duration {
	if val, ok := f.values[key]; ok {
		// 通过xconv.Duration将字符串值转为time.Duration（支持"1s"/"2m"/"3h"等格式）
		return rconv.Duration(val)
	}

	// 不存在则返回默认值（若有），否则返回0
	if len(def) > 0 {
		return def[0]
	}

	return 0
}

func (f *flagSet) int(key string, def ...int) int {
	if val, ok := f.values[key]; ok {
		return rconv.Int(val)
	}

	if len(def) > 0 {
		return def[0]
	}

	return 0
}

func (f *flagSet) int8(key string, def ...int8) int8 {
	if val, ok := f.values[key]; ok {
		return rconv.Int8(val)
	}

	if len(def) > 0 {
		return def[0]
	}

	return 0
}

func (f *flagSet) int16(key string, def ...int16) int16 {
	if val, ok := f.values[key]; ok {
		return rconv.Int16(val)
	}

	if len(def) > 0 {
		return def[0]
	}

	return 0
}

func (f *flagSet) int32(key string, def ...int32) int32 {
	if val, ok := f.values[key]; ok {
		return rconv.Int32(val)
	}

	if len(def) > 0 {
		return def[0]
	}

	return 0
}

func (f *flagSet) int64(key string, def ...int64) int64 {
	if val, ok := f.values[key]; ok {
		return rconv.Int64(val)
	}

	if len(def) > 0 {
		return def[0]
	}

	return 0
}

func (f *flagSet) uint(key string, def ...uint) uint {
	if val, ok := f.values[key]; ok {
		return rconv.Uint(val)
	}

	if len(def) > 0 {
		return def[0]
	}

	return 0
}

func (f *flagSet) uint8(key string, def ...uint8) uint8 {
	if val, ok := f.values[key]; ok {
		return rconv.Uint8(val)
	}

	if len(def) > 0 {
		return def[0]
	}

	return 0
}

func (f *flagSet) uint16(key string, def ...uint16) uint16 {
	if val, ok := f.values[key]; ok {
		return rconv.Uint16(val)
	}

	if len(def) > 0 {
		return def[0]
	}

	return 0
}

func (f *flagSet) uint32(key string, def ...uint32) uint32 {
	if val, ok := f.values[key]; ok {
		return rconv.Uint32(val)
	}

	if len(def) > 0 {
		return def[0]
	}

	return 0
}

func (f *flagSet) uint64(key string, def ...uint64) uint64 {
	if val, ok := f.values[key]; ok {
		return rconv.Uint64(val)
	}

	if len(def) > 0 {
		return def[0]
	}

	return 0
}

func (f *flagSet) float32(key string, def ...float32) float32 {
	if val, ok := f.values[key]; ok {
		return rconv.Float32(val)
	}

	if len(def) > 0 {
		return def[0]
	}

	return 0
}

func (f *flagSet) float64(key string, def ...float64) float64 {
	if val, ok := f.values[key]; ok {
		return rconv.Float64(val)
	}

	if len(def) > 0 {
		return def[0]
	}

	return 0
}
